package com.bt.lms.ui.page.sys.role;

import com.alibaba.fastjson.JSONObject;
import com.bt.lms.constants.BOConstant;
import com.bt.lms.constants.SysBizTypeConstant;
import com.bt.lms.entity.Role;
import com.bt.lms.entity.User;
import com.bt.lms.entity.page.Page;
import com.bt.lms.main.BotLmsApp;
import com.bt.lms.network.msg.ReqMsg;
import com.bt.lms.network.msg.RespMsg;
import com.bt.lms.ui.page.common.PageLocation;
import com.bt.lms.ui.page.sys.ServerInfo;
import com.bt.lms.ui.page.sys.page.paging.PagePaging;
import com.bt.lms.ui.page.sys.style.LabStyle;
import com.bt.lms.ui.page.sys.utils.*;
import com.bt.lms.ui.page.sys.vo.RoleTableViewVo;
import com.bt.lms.ui.page.sys.vo.UserListInfo;
import com.bt.lms.ui.vo.PageSkipInfo;
import javafx.collections.FXCollections;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.util.Callback;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 添加用户列表
 *
 * @author 徐大永
 */
public class PageAddUserList extends VBox {

    /**
     * 针对的角色
     */
    private RoleTableViewVo roleTableViewVo;

    /**
     * 界面跳转信息
     */
    private PageSkipInfo pageSkipInfo;

    /**
     * 源页
     */
    private final Integer srcPage;

    //界面 定位 列表 分页 控制
    /**
     * 列表
     */
    private TableView<UserListInfo> userTV;

    /**
     * 分页区
     */
    private PagePaging pagePaging;

    /**
     * 控制区
     */
    private HBox commandHBox;

    //事件（产生数据变化） 分页  确认  返回
    /**
     * 分页事件
     */
    private final PageAction pageAction;

    //数据（动态）  列表  页数  条数   勾选的用户
    /**
     * 分页模型（列表）
     */
    private Page<UserListInfo> page = new Page<>();

    /**
     * 勾选的用户
     */
    private List<Long> userIds;

    /**
     * 全部的用户
     */
    private final List<CheckBox> sumUserCBs = new ArrayList<>();

    /**
     * 构建添加用户界面
     *
     * @param roleTableViewVo 针对的角色
     * @param pageSkipInfo    界面跳转信息
     * @param srcPage         源页码
     */
    public PageAddUserList(RoleTableViewVo roleTableViewVo, PageSkipInfo pageSkipInfo, Integer srcPage) {

        //维护
        setRoleTableViewVo(roleTableViewVo);//当前角色信息
        setPageSkipInfo(pageSkipInfo);
        this.srcPage = srcPage;
        //分页事件
        pageAction = new PageAction();
        pageAction.setPageAddUserList(this);

        //布局
        this.setPrefWidth(BotLmsApp.PER_WIGHT);
        this.setSpacing(20);

        //界面初始化
        uiInit();

        //加载数据并渲染
        loadAndRenderPage();
    }

    /**
     * 界面初始化
     */
    private void uiInit() {

        //定位
        PageLocation pageLocation = new PageLocation("系统管理", "角色权限管理", "添加角色用户", roleTableViewVo.getName() + "角色");

        //说明
        Label explainLab = new Label("添加" + roleTableViewVo.getName() + "角色用户");

        //列表
        this.userTV = new TableView<>();
        userTVInit();

        //分页
        this.pagePaging = new PagePaging(this, this.getClass());

        //控制
        this.commandHBox = new HBox();
        commandHBoxInit();

        //组件添加
        this.getChildren().addAll(pageLocation, explainLab, userTV, pagePaging, commandHBox);

    }

    /**
     * 列表初始化
     */
    private void userTVInit() {

        //列表
        TableView<UserListInfo> userTV = getUserTV();

        //1.列头
        TableColumn<UserListInfo, Long> operateTC = new TableColumn<>("是否添加");
        TableColumn<UserListInfo, String> accountNumberTC = new TableColumn<>("账号");
        TableColumn<UserListInfo, String> nameTC = new TableColumn<>("用户姓名");
        TableColumn<UserListInfo, List<Role>> rolesTC = new TableColumn<>("角色");
        TableColumn<UserListInfo, String> createdNameTC = new TableColumn<>("创建人");
        TableColumn<UserListInfo, LocalDateTime> createdTimeTC = new TableColumn<>("创建时间");
        TableColumn<UserListInfo, LocalDateTime> loginTimeTC = new TableColumn<>("最近登录时间");
        TableColumn<UserListInfo, Integer> statusTC = new TableColumn<>("状态");

        //2.添加
        userTV.getColumns().addAll(operateTC, accountNumberTC, nameTC, rolesTC, createdNameTC, createdTimeTC, loginTimeTC, statusTC);
        //3.映射
        operateTC.setCellValueFactory(new PropertyValueFactory<>("id"));
        accountNumberTC.setCellValueFactory(new PropertyValueFactory<>("accountNumber"));
        nameTC.setCellValueFactory(new PropertyValueFactory<>("name"));
        rolesTC.setCellValueFactory(new PropertyValueFactory<>("roles"));
        createdNameTC.setCellValueFactory(new PropertyValueFactory<>("createdName"));
        createdTimeTC.setCellValueFactory(new PropertyValueFactory<>("createdTime"));
        loginTimeTC.setCellValueFactory(new PropertyValueFactory<>("loginTime"));
        statusTC.setCellValueFactory(new PropertyValueFactory<>("status"));
        //4.自定义渲染
        customVRay(operateTC, rolesTC, createdTimeTC, loginTimeTC, statusTC);
    }

    /**
     * 自定义界面渲染
     *
     * @param operateTC     操作列
     * @param rolesTC       角色列
     * @param createdTimeTC 创建时间列
     * @param loginTimeTC   最近登录时间列
     * @param statusTC      状态列
     */
    private void customVRay(TableColumn<UserListInfo, Long> operateTC
            , TableColumn<UserListInfo, List<Role>> rolesTC, TableColumn<UserListInfo, LocalDateTime> createdTimeTC
            , TableColumn<UserListInfo, LocalDateTime> loginTimeTC
            , TableColumn<UserListInfo, Integer> statusTC) {

        Map<Long, Boolean> idMap = new HashMap<>();

        //操作列
        operateTC.setCellFactory(new Callback<TableColumn<UserListInfo, Long>, TableCell<UserListInfo, Long>>() {
            @Override
            public TableCell<UserListInfo, Long> call(TableColumn<UserListInfo, Long> param) {
                return new TableCell<UserListInfo, Long>() {
                    @Override
                    protected void updateItem(Long userId, boolean empty) {
                        super.updateItem(userId, empty);

                        if (userId != null) {
                            //要显示的框
                            CheckBox userCB = new CheckBox();
                            userCB.setId(String.valueOf(userId));
                            //判断是否出现过
                            Boolean aBoolean = idMap.get(userId);
                            if (aBoolean == null)//没有出现过
                                idMap.put(userId, true);
                            else
                                sumUserCBs.add(userCB);

                            setGraphic(userCB);
                        } else {
                            setGraphic(null);
                        }
                    }
                };
            }
        });

        //角色列
        rolesTC.setCellFactory(new Callback<TableColumn<UserListInfo, List<Role>>, TableCell<UserListInfo, List<Role>>>() {
            @Override
            public TableCell<UserListInfo, List<Role>> call(TableColumn<UserListInfo, List<Role>> param) {
                return new TableCell<UserListInfo, List<Role>>() {
                    @Override
                    protected void updateItem(List<Role> roles, boolean empty) {
                        super.updateItem(roles, empty);
                        if (roles != null) {

                            StringBuilder roleNameSB = new StringBuilder();
                            for (Role role : roles) {
                                roleNameSB.append(role.getName());
                            }
                            String roleNameStr = new String(roleNameSB);
                            Label roleNameLab = new Label(roleNameStr);
                            setGraphic(roleNameLab);
                        }else {
                            setGraphic(null);
                        }
                    }
                };
            }
        });

        //创建时间列
        createdTimeTC.setCellFactory(new Callback<TableColumn<UserListInfo, LocalDateTime>, TableCell<UserListInfo, LocalDateTime>>() {
            @Override
            public TableCell<UserListInfo, LocalDateTime> call(TableColumn<UserListInfo, LocalDateTime> param) {
                return new TableCell<UserListInfo, LocalDateTime>() {
                    @Override
                    protected void updateItem(LocalDateTime createdTime, boolean empty) {
                        super.updateItem(createdTime, empty);
                        if (createdTime != null) {
                            LocalDate createdTimeLD = createdTime.toLocalDate();
                            String createdTimeStr = createdTimeLD.toString();
                            Label createdTimeLab = new Label(createdTimeStr);
                            setGraphic(createdTimeLab);
                        }else {
                            setGraphic(null);
                        }
                    }
                };
            }
        });

        //登录时间列
        loginTimeTC.setCellFactory(new Callback<TableColumn<UserListInfo, LocalDateTime>, TableCell<UserListInfo, LocalDateTime>>() {
            @Override
            public TableCell<UserListInfo, LocalDateTime> call(TableColumn<UserListInfo, LocalDateTime> param) {
                return new TableCell<UserListInfo, LocalDateTime>() {
                    @Override
                    protected void updateItem(LocalDateTime loginTime, boolean empty) {
                        super.updateItem(loginTime, empty);
                        if (loginTime != null) {
                            LocalDate loginTimeLD = loginTime.toLocalDate();
                            String loginTimeStr = loginTimeLD.toString();
                            Label loginTimeLab = new Label(loginTimeStr);
                            setGraphic(loginTimeLab);
                        }else {
                            setGraphic(null);
                        }
                    }
                };
            }
        });

        //状态列
        statusTC.setCellFactory(new Callback<TableColumn<UserListInfo, Integer>, TableCell<UserListInfo, Integer>>() {
            @Override
            public TableCell<UserListInfo, Integer> call(TableColumn<UserListInfo, Integer> param) {
                return new TableCell<UserListInfo, Integer>() {
                    @Override
                    protected void updateItem(Integer status, boolean empty) {
                        super.updateItem(status, empty);
                        if (status != null) {

                            if (status.equals(BOConstant.USER_STATUS_START)) {
                                Label start = new Label("启用");
                                LabStyle.status(start, LabStyle.OPEN);
                                setGraphic(start);
                            } else if (status.equals(BOConstant.USER_STATUS_STOP)) {
                                Label stop = new Label("停用");
                                LabStyle.status(stop, LabStyle.STOP);
                                setGraphic(stop);
                            }


                        }else {
                            setGraphic(null);
                        }
                    }
                };
            }
        });

    }

    /**
     * 控制初始化
     */
    private void commandHBoxInit() {

        //控制盒子
        HBox commandHBox = this.commandHBox;

        //布局
        commandHBox.setAlignment(Pos.CENTER);
        commandHBox.setSpacing(10);

        //组件
        MyButton notarizeBtn = new MyButton("确认");
        //事件
        NotarizeAction notarizeAction = new NotarizeAction();
        notarizeAction.setRoleId(this.roleTableViewVo.getId());
        notarizeAction.setPageAddUserList(this);
        notarizeBtn.setOnAction(notarizeAction);

        //返回
        MyButton cancelBtn = new MyButton("返回");
        //事件
        CancelAction cancelAction = new CancelAction();
        cancelAction.setPageAddUserList(this);
        cancelBtn.setOnAction(cancelAction);

        commandHBox.getChildren().addAll(notarizeBtn, cancelBtn);

    }

    /**
     * 加载数据并渲染
     */
    private void loadAndRenderPage() {

        //1.确认页数
        Page<User> userPage = new Page<>();
        if (getPage() != null) {
            userPage.setCurrent(getPage().getCurrent());//当前页数
            userPage.setSize(getPage().getSize());//每页条数
        }
        //2.请求数据
        Page page = reqUserData(userPage);
        //3.处理数据格式
        if (page != null) {
            getPage().setTotal(page.getTotal());//设置分页模型的总条数
            List<UserListInfo> userListInfos = new ArrayList<>();
            List records = page.getRecords();
            if (records != null) {//没有获取到数据
                for (Object obj : records) {
                    UserListInfo userListInfo = JSONObject.parseObject(obj.toString(), UserListInfo.class);
                    userListInfos.add(userListInfo);
                }
                //4.渲染进界面
                //4.1 渲染列表
                TableView<UserListInfo> userTV = getUserTV();
                userTV.setItems(FXCollections.observableArrayList(userListInfos));
                //4.2 渲染分页模型
                //4.2.1 维护分页区数据
                //总页数
                Long total = page.getTotal();//总条数
                Integer size = page.getSize();//每页数
                long sumPage = total % size == 0 ? total / size : total / size + 1;
                getPagePaging().setSumPage(sumPage);
                //4.2.2 渲染分页区
                getPagePaging().loadAndRenderPage();
            } else
                runtimeHint("未能获取到数据，请联系客服。");

        }
    }


    /**
     * 数据请求
     *
     * @param userPage 分页模型
     * @return 分页数据
     */
    private Page reqUserData(Page<User> userPage) {

        //准备数据
        Role role = new Role();
        role.setId(roleTableViewVo.getId());

        List dataList = new ArrayList();
        dataList.add(userPage);
        dataList.add(role);

        //1.组包
        ReqMsg reqMsg = Encode.encodeToMsg(dataList, SysBizTypeConstant.USER_ROLE_NOT_USER);
        byte[] reqBytes = reqMsg.toBytes();
        //2.开网
        try (Socket socket = new Socket(ServerInfo.IP, ServerInfo.PORT)) {
            //3.发送
            OutputStream out = socket.getOutputStream();
            out.write(reqBytes);
            //4.接收响应
            InputStream in = socket.getInputStream();
            List<byte[]> receive = NetWorkUtils.receive(in);
            byte[] respBytes = ArrayUtils.joinBytes(receive);
            RespMsg respMsg = RespMsg.toRespMsg(respBytes);
            //5.关闭资源
            in.close();
            out.close();
            //6.处理结果集
            Short status = respMsg.getStatus();
            if (status.equals(RespMsg.NETWORK_STATUS_NORMAL)) {
                String data = respMsg.getData();
                return JSONObject.parseObject(data, Page.class);
            } else
                return new Page();

        } catch (IOException e) {
            runtimeHint("网络异常，请检查连接或联系客服。");
            return null;
        }
    }

    /**
     * 运行提示（弹窗提示）
     *
     * @param hint 提示语
     */
    private void runtimeHint(String hint) {

        Alert alert = new Alert(Alert.AlertType.WARNING);
        alert.setTitle("提示");
        alert.setHeaderText(null);
        alert.setContentText(hint);
        alert.showAndWait();
    }


    /**
     * 分页事件
     */
    private static class PageAction implements EventHandler {

        /**
         * 事件所属界面
         */
        private PageAddUserList pageAddUserList;

        @Override
        public void handle(Event event) {

            //获取当前页码
            PageAddUserList pageAddUserList = getPageAddUserList();
            Page<UserListInfo> page = pageAddUserList.getPage();
            Integer current = page.getCurrent();//当前页
            //总页数
            Integer size = page.getSize();
            Long total = page.getTotal();
            long sumPage = total % size == 0 ? total / size : total / size + 1;

            try {
                //点击的是按钮
                MyButton btn = (MyButton) event.getSource();
                String text = btn.getText();
                if (text.matches("[0-9]+")) {//点击的是数字
                    if (current != Integer.parseInt(text)) {
                        page.setCurrent(Integer.valueOf(text));
                        pageAddUserList.loadAndRenderPage();
                    }
                } else if ("GO".equals(text)) {
                    PagePaging pagePaging = pageAddUserList.getPagePaging();//获取分页模型
                    TextField pageNumberTF = pagePaging.getPageNumberTF();//获取输入框
                    String pageStr = pageNumberTF.getText().trim();
                    if (pageStr.matches("[0-9]+")) {
                        long pageL = Long.parseLong(pageStr);
                        if (pageL > 0 && pageL <= sumPage) {
                            page.setCurrent((int) pageL);
                            pageAddUserList.loadAndRenderPage();
                        } else
                            pageAddUserList.runtimeHint("请输入存在的页码。");
                    } else {
                        pageAddUserList.runtimeHint("请输入数字。");
                    }
                }
            } catch (Exception e) {
                MyLabel lab = (MyLabel) event.getSource();
                String text = lab.getText();
                if (PagePaging.FIRST_STR.equals(text)) {
                    if (current > 1) {
                        page.setCurrent(1);
                        pageAddUserList.loadAndRenderPage();
                    }
                } else if (PagePaging.LAST_STR.equals(text)) {
                    if (current > 1) {
                        page.setCurrent(current - 1);
                        pageAddUserList.loadAndRenderPage();
                    }
                } else if (PagePaging.NEXT_STR.equals(text)) {
                    if (current < sumPage) {
                        page.setCurrent(current + 1);
                        pageAddUserList.loadAndRenderPage();
                    }
                } else if (PagePaging.FINALLY_STR.equals(text)) {
                    if (current < sumPage) {
                        page.setCurrent((int) sumPage);
                        pageAddUserList.loadAndRenderPage();
                    }
                }
            }
        }

        public PageAddUserList getPageAddUserList() {
            return pageAddUserList;
        }

        public void setPageAddUserList(PageAddUserList pageAddUserList) {
            this.pageAddUserList = pageAddUserList;
        }
    }

    /**
     * 确认事件
     */
    private static class NotarizeAction implements EventHandler {

        /**
         * 所在界面
         */
        private PageAddUserList pageAddUserList;

        /**
         * 当前角色
         */
        private Long roleId;

        @Override
        public void handle(Event event) {

            //选中的用户集
            List<Long> userIds = new ArrayList<>();

            //处理数据
            //所在界面
            PageAddUserList pageAddUserList = getPageAddUserList();
            //界面拥有的所有选择框
            for (CheckBox checkBox : pageAddUserList.sumUserCBs) {
                boolean selected = checkBox.isSelected();//判断是否被选中
                if (selected) {
                    String id = checkBox.getId();
                    long userId = Long.parseLong(id);
                    userIds.add(userId);
                }
            }

            //准备要发送的数据
            Long roleId = getRoleId();
            List dataList = new ArrayList();
            dataList.add(userIds);
            dataList.add(roleId);

            //1.组包
            ReqMsg reqMsg = Encode.encodeToMsg(dataList, SysBizTypeConstant.USER_ROLE_ADD_USER);
            byte[] reqBytes = reqMsg.toBytes();
            //2.开网
            try (Socket socket = new Socket(ServerInfo.IP, ServerInfo.PORT)) {
                //3.发送
                OutputStream out = socket.getOutputStream();
                out.write(reqBytes);
                //4.接收响应
                InputStream in = socket.getInputStream();
                List<byte[]> receive = NetWorkUtils.receive(in);
                byte[] respBytes = ArrayUtils.joinBytes(receive);
                //5.资源关闭
                in.close();
                out.close();
                //6.处理数据
                RespMsg respMsg = RespMsg.toRespMsg(respBytes);
                if (respMsg.getStatus().equals(RespMsg.NETWORK_STATUS_NORMAL)) {
                    //成功
                    succeed();
                    //界面跳转（返回角色权限当前页）
                    Page<Role> rolePage = new Page<>();
                    rolePage.setCurrent(pageAddUserList.srcPage);
                    NetWorkUtils.reqRolePagingPage(pageAddUserList.pageSkipInfo, rolePage);
                } else {
                    getPageAddUserList().runtimeHint("添加失败，请稍候重试，或联系客服");
                }
            } catch (IOException e) {
                getPageAddUserList().runtimeHint("添加失败，请检查网络，或联系客服");
            }
        }

        /**
         * 成功方法
         */
        private void succeed() {

            Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setTitle("成功");
            alert.setHeaderText(null);
            alert.setContentText("添加成功");
            alert.showAndWait();
        }

        public Long getRoleId() {
            return roleId;
        }

        public void setRoleId(Long roleId) {
            this.roleId = roleId;
        }

        public PageAddUserList getPageAddUserList() {
            return pageAddUserList;
        }

        public void setPageAddUserList(PageAddUserList pageAddUserList) {
            this.pageAddUserList = pageAddUserList;
        }
    }

    /**
     * 返回事件
     */
    private static class CancelAction implements EventHandler {

        /**
         * 所属界面
         */
        private PageAddUserList pageAddUserList;

        @Override
        public void handle(Event event) {

            //界面跳转（返回角色权限当前页）
            PageAddUserList pageAddUserList = getPageAddUserList();
            Page<Role> rolePage = new Page<>();
            rolePage.setCurrent(pageAddUserList.srcPage);
            NetWorkUtils.reqRolePagingPage(pageAddUserList.pageSkipInfo, rolePage);
        }


        public PageAddUserList getPageAddUserList() {
            return pageAddUserList;
        }

        public void setPageAddUserList(PageAddUserList pageAddUserList) {
            this.pageAddUserList = pageAddUserList;
        }
    }

    public Page<UserListInfo> getPage() {
        return page;
    }

    public void setPage(Page<UserListInfo> page) {
        this.page = page;
    }

    public RoleTableViewVo getRoleTableViewVo() {
        return roleTableViewVo;
    }

    public void setRoleTableViewVo(RoleTableViewVo roleTableViewVo) {
        this.roleTableViewVo = roleTableViewVo;
    }

    public TableView<UserListInfo> getUserTV() {
        return userTV;
    }

    public PagePaging getPagePaging() {
        return pagePaging;
    }

    public PageSkipInfo getPageSkipInfo() {
        return pageSkipInfo;
    }

    public void setPageSkipInfo(PageSkipInfo pageSkipInfo) {
        this.pageSkipInfo = pageSkipInfo;
    }
}
